function returnConfig() {
  const _ = {
    // 全局配置
    config: {
      url: '',
      dataType: '',
      responseType: '',
      header: {},
      data: {},
      contentType: 'form'
    },

    // 拦截器
    interceptors: {
      request: null,
      response: null,
      global: {
        request: null,
        response: null
      },

      /**
       * 请求拦截器(全局、局部)
       * @param {Object} config
       * @param {number} count - 运行次数，用于递归的统计
       */
      req(config, count) {
        const type = (count === 1 ? '.global' : '') + '.request'
        const fnPath = 'interceptors' + type
        const fn = _.getObjPathVal(fnPath)

        if (typeof fn === 'function') {
          let ret = fn(config)

          if (ret === false || typeof ret === 'undefined') {
            return false
          }

          return count === 2 ? ret : _.interceptors.req(ret, 2)
        }

        if (count === 2) return config
        return _.interceptors.req(config, 2)
      },

      /**
       * 响应拦截器(全局、局部)
       * @param {Object} res
       * @param {number} count - 运行次数，用于递归的统计
       */
      rep(res, count) {
        const type = (count === 1 ? '.global' : '') + '.response'
        const fnPath = 'interceptors' + type
        const fn = _.getObjPathVal(fnPath)

        if (typeof fn === 'function') {
          let ret = fn(res)

          // 返回promise中reject的值
          if (Object.prototype.toString.call(ret) === '[object Promise]') {
            return ret
          }

          if (ret === false || typeof ret === 'undefined') {
            return false
          }

          return count === 2 ? ret : _.interceptors.rep(ret, 2)
        }

        if (count === 2) return res
        return _.interceptors.rep(res, 2)
      }
    },

    // 合并
    merge: {
      /**
       * 合并 全局配置
       * @param {Object} defaultC - 默认配置
       * @param {Object} newC - 新配置
       */
      globalConfig(defaultC, newC) {
        return {
          ...defaultC,
          ...newC
        }
      },

      /**
       * 合并配置（全局配置+实例中的配置,实例中的优先级更高）
       * @param {Object} config
       * @param {string} method
       */
      config(config, method) {
        const url = _.merge.url(_.config.url, config.url)
        const contentType = _.merge.contentType(config.contentType || _.config.contentType)
        const header = {
          contentType,
          ...config.header,
          ..._.config.header
        }
        const newConfig = {
          ...config,
          ..._.config,
          url,
          method,
          header
        }

        delete newConfig.contentType
        return newConfig
      },

      /**
       * 合并url，返回完整的资源定位符
       * @param {string} beforeUrl - 全局配置中设置的基地址
       * @param {string} afterUrl - request实例中设置的url
       */
      url(beforeUrl, afterUrl) {
        const bLen = beforeUrl.length
        const aLen = afterUrl.length
        const beforeHasSlash = beforeUrl.lastIndexOf('/') + 1 === bLen
        const afterHasSlash = afterUrl.indexOf('/') === 0

        if (aLen === 0 || (bLen !== 0 && !_.isCompleteUrl(beforeUrl))) {
          _.error('url参数不完整或者错误')
        }

        if (_.isCompleteUrl(afterUrl)) {
          return beforeUrl
        }

        if (beforeHasSlash && afterHasSlash) {
          return beforeUrl + afterUrl.substr(1)
        }

        if (beforeHasSlash || afterHasSlash) {
          return beforeUrl + afterUrl
        }

        if (!beforeHasSlash && !afterHasSlash) {
          return beforeUrl + '/' + afterUrl
        }
      },

      /**
       * 合并header中content-type参数, 默认添加utf-8
       * @param {string} type ["form"] content-type类型
       */
      contentType(type = 'form') {
        let tmpStr = ''

        switch (type) {
          case 'form':
            tmpStr = 'application/x-www-form-urlencoded'
            break
          case 'json':
            tmpStr = 'application/json'
            break
          case 'file':
            tmpStr = 'multipart/form-data'
            break
          default:
            _.error('contentType参数错误')
        }

        return tmpStr + ';charset=UTF-8'
      }
    },

    xhr: {
      // 数据回传 成功
      success(res, config, canRetRep, resolve, reject) {
        const newRes = _.interceptors.rep(res, 1)
        const bool = _.xhr.commonIntercept(newRes, config, canRetRep, reject)

        if (bool === false) return false
        config.success ? config.success(newRes) : resolve(newRes)
      },

      // 数据回传 失败
      fail(err, config, canRetRep, reject) {
        const newErr = _.interceptors.rep(err, 1)
        const bool = _.xhr.commonIntercept(newErr, config, canRetRep, reject)

        if (bool === false) return false
        config.fail ? config.fail(newErr) : reject(newErr)
      },

      // 数据回传 完成
      complete(res, config, canRetRep) {
        if (!config.complete || !canRetRep.status) return false

        config.complete(res)
      },

      // 公共拦截部分
      commonIntercept(obj, { fail }, type, reject) {
        // 数据被拦截, 没有返回值
        if (obj === false) {
          type.status = false
          return false
        }

        // 数据被拦截, 主动抛出错误
        if (Object.prototype.toString.call(obj) === '[object Promise]') {
          obj.catch(fail || reject)
          return false
        }
      }
    },

    /**
     * 是否是完整的 url
     * @param {string} url - 统一资源定位符
     */
    isCompleteUrl(url) {
      return /(http|https):\/\/([\w.]+\/?)\S*/.test(url)
    },

    /**
     * 获取 根据对象的属性路径的值
     * @param {string} objPath - 对象的属性路径
     */
    getObjPathVal(objPath) {
      const splitList = objPath.split('.')
      let tmpObj = _

      splitList.forEach(key => {
        tmpObj = tmpObj[key]
      })

      return tmpObj
    },

    /**
     * 公共请求方法, 支持对象中callback或Promise
     * @param {Object} config - 完整的配置数据
     */
    request(config) {
      const canRetRep = { status: true }
      const newConfig = _.interceptors.req(config, 1)
      let example, ret

      if (newConfig === false) return

      ret = new Promise((resolve, reject) => {
        example = uni.request({
          ...newConfig,
          success: res => {
            _.xhr.success(res, newConfig, canRetRep, resolve, reject)
          },
          fail: err => {
            _.xhr.fail(err, newConfig, canRetRep, reject)
          },
          complete: res => {
            _.xhr.complete(res, newConfig, canRetRep)
          }
        })
      })

      // @TODO: 隐式修改原型
      Object.__proto__.example = example

      return ret
    },

    /**
     * 抛出错误
     * @param {string} msg 错误信息
     */
    error(msg) {
      throw new Error('[request error]: ' + msg)
    }
  }
  return _
}

export default returnConfig
